﻿using System;
using GeoAPI.Geometries;

namespace NetTopologySuite.Algorithm
{
	[Obsolete("Use Centroid instead")]
	public class CentroidArea
	{
		public void Add(IGeometry geom)
		{
			if (geom is IPolygon)
			{
				IPolygon polygon = (IPolygon)geom;
				this.BasePoint = polygon.ExteriorRing.GetCoordinateN(0);
				this.Add(polygon);
				return;
			}
			if (geom is IGeometryCollection)
			{
				IGeometryCollection geometryCollection = (IGeometryCollection)geom;
				for (int i = 0; i < geometryCollection.NumGeometries; i++)
				{
					this.Add(geometryCollection.GetGeometryN(i));
				}
			}
		}

		public void Add(Coordinate[] ring)
		{
			this.BasePoint = ring[0];
			this.AddShell(ring);
		}

		public Coordinate Centroid
		{
			get
			{
				Coordinate coordinate = new Coordinate();
				if (System.Math.Abs(this._areasum2) > 0.0)
				{
					coordinate.X = this._cg3.X / 3.0 / this._areasum2;
					coordinate.Y = this._cg3.Y / 3.0 / this._areasum2;
				}
				else
				{
					coordinate.X = this._centSum.X / this._totalLength;
					coordinate.Y = this._centSum.Y / this._totalLength;
				}
				return coordinate;
			}
		}

		private Coordinate BasePoint
		{
			set
			{
				if (this._basePt == null)
				{
					this._basePt = value;
				}
			}
		}

		private void Add(IPolygon poly)
		{
			this.AddShell(poly.ExteriorRing.Coordinates);
			foreach (ILineString lineString in poly.InteriorRings)
			{
				this.AddHole(lineString.Coordinates);
			}
		}

		private void AddShell(Coordinate[] pts)
		{
			bool isPositiveArea = !CGAlgorithms.IsCCW(pts);
			for (int i = 0; i < pts.Length - 1; i++)
			{
				this.AddTriangle(this._basePt, pts[i], pts[i + 1], isPositiveArea);
			}
			this.AddLinearSegments(pts);
		}

		private void AddHole(Coordinate[] pts)
		{
			bool isPositiveArea = CGAlgorithms.IsCCW(pts);
			for (int i = 0; i < pts.Length - 1; i++)
			{
				this.AddTriangle(this._basePt, pts[i], pts[i + 1], isPositiveArea);
			}
			this.AddLinearSegments(pts);
		}

		private void AddTriangle(Coordinate p0, Coordinate p1, Coordinate p2, bool isPositiveArea)
		{
			double num = isPositiveArea ? 1.0 : -1.0;
			CentroidArea.Centroid3(p0, p1, p2, ref this._triangleCent3);
			double num2 = CentroidArea.Area2(p0, p1, p2);
			this._cg3.X += num * num2 * this._triangleCent3.X;
			this._cg3.Y += num * num2 * this._triangleCent3.Y;
			this._areasum2 += num * num2;
		}

		private static void Centroid3(Coordinate p1, Coordinate p2, Coordinate p3, ref Coordinate c)
		{
			c.X = p1.X + p2.X + p3.X;
			c.Y = p1.Y + p2.Y + p3.Y;
		}

		private static double Area2(Coordinate p1, Coordinate p2, Coordinate p3)
		{
			return (p2.X - p1.X) * (p3.Y - p1.Y) - (p3.X - p1.X) * (p2.Y - p1.Y);
		}

		private void AddLinearSegments(Coordinate[] pts)
		{
			for (int i = 0; i < pts.Length - 1; i++)
			{
				double num = pts[i].Distance(pts[i + 1]);
				this._totalLength += num;
				double num2 = (pts[i].X + pts[i + 1].X) / 2.0;
				this._centSum.X += num * num2;
				double num3 = (pts[i].Y + pts[i + 1].Y) / 2.0;
				this._centSum.Y += num * num3;
			}
		}

		private Coordinate _basePt;

		private Coordinate _triangleCent3 = new Coordinate();

		private double _areasum2;

		private readonly Coordinate _cg3 = new Coordinate();

		private readonly Coordinate _centSum = new Coordinate();

		private double _totalLength;
	}
}
